#pragma once

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <memory>
#include <functional>

#include "log.hpp"
#include "connection.hpp"
#include "service.hpp"

#include "threadpool.hpp"
#include "Inetaddr.hpp"
#include "lockguard.hpp"

using namespace log_namespace;

// 不应该让HandleConnection来处理报文
class HandleConnection
{
public:
    HandleConnection(handler_t process)
        : _process(process)
    {
    }

    void HandleRecvr(myConnection *conn)
    {
        errno = 0;
        // 直接读取
        // LOG(DEBUG, "client 给我发了消息：%d\n", conn->getsocketfd());
        while (true)
        {
            char buffer[1024];
            // 不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据
            ssize_t n = ::recv(conn->getsocketfd(), buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                conn->appendInBuffer(buffer);
            }
            else
            {
                if (errno == EWOULDBLOCK)
                {
                    break;
                }
                else if (errno == EINTR)
                {
                    continue;
                }
                else
                {
                    conn->_handler_excepter(conn);
                    return;
                }
            }
        }
        // 交给业务处理
        // 走到这，意味着数据接收方已经取完所有数据，放到buffer中了
        std::cout << "inbuffer中的内容：" << conn->getinBuffer() << std::endl;
        // 666666666666666666666666666666666666666666666666666666666666666666666666666666
        using task_t = std::function<void()>;
        IOService parse;
        task_t t = std::bind(&IOService::IOexecute, &parse, conn);
        threadPool<task_t>::getInstance()->enqueue(t);

        // _process(conn);

        // 666666666666666666666666666666666666666666666666666666666666666666666666666666
    }

    void HandleSender(myConnection *conn)
    {
        errno = 0;
        while (true)
        {
            // 这里的 conn->getoutBuffer() 得到的是语言级别的缓冲区
            // send将会把 这个语言级别的缓冲区，放到系统级别的缓冲区中
            // 这个系统级别的缓冲区对应的就是  连接对应的 文件描述符对应的发送缓冲区
            ssize_t n = ::send(conn->getsocketfd(), conn->getoutBuffer().c_str(), conn->getoutBuffer().size(), 0);
            if (n > 0)
            {
                // n作为send后发送成功的字节数，
                // 每次发送完毕之后, 应该吧getoutBuffer的这个n个字符删除
                conn->DiscardoutBuffer(n);
                if (conn->getoutBuffer().empty())
                {
                    // 已经把连接对应的发送缓冲区中的数据发送完毕了
                    break;
                }
            }
            else if (n == 0)
            {
                return;
            }
            else
            {
                // 小于0，有以下情况，此时根据errno进行区分
                // case1: 发送缓冲区已经写满了
                if (errno == EWOULDBLOCK)
                {
                    break;
                }
                // case2: send执行过程中被信号中断了
                // 比如正在把数据往发送缓冲区拷贝时
                // 信号把发送过程中断了
                else if (errno == EINTR)
                {
                    continue;
                }
                // case3: 发生异常
                else
                {
                    conn->_handler_excepter(conn);
                    return;
                }
            }
        }
        // 走到这， 一定是满足了 errno == EWOULDBLOCK 这个条件
        // case1: 发送条件不满足，即缓冲区被写满了
        if (!conn->getoutBuffer().empty())
        {
            // 下面这句话就会把发送缓冲区中的数据进行处理，
            // epoll 会让系统把所有想要发到发送缓冲区的内容发完之后才会继续进行
            conn->_R->EnableConnectiontforReadandWrite(conn->getsocketfd(), true, true);
        }
        // case2: 已经发完了，此时就不能在对写事件进行关心了
        else
        {
            conn->_R->EnableConnectiontforReadandWrite(conn->getsocketfd(), true, false);
        }
    }

    void HandleExceptr(myConnection *conn)
    {
        // 整个代码所有的逻辑异常处理，都会通过这个函数统一处理
        // 删除连接
        conn->_R->DelConnection(conn->getsocketfd());
    }

private:
    handler_t _process;
};
